#include <opencv2/opencv.hpp>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

////////////////////////////////////////////////////////////////////////////////
//
// @compile g++ ScreenReader.cpp -o screenReader -lX11 -lXext -Ofast -mfpmath=both -march=native -m64 -funroll-loops -mavx2 `pkg-config --cflags --libs opencv4` && ./screenReader
// @see https://stackoverflow.com/questions/24988164/c-fast-screenshots-in-linux-for-use-with-opencv/39781697
// @see https://github.com/cnlohr/x11framegrab/blob/master/x11framegrab.c
// @todos chatch keystrokes => take screenshot / commandline parameters/ background deamon / beep (optional) / save img with basename + number + format / optional acustic beep 
// k9qwfbVuHk9nHCRD2f5N
////////////////////////////////////////////////////////////////////////////////
class ScreenReader
{
    
public:

    ScreenReader(int x, int y, int width, int height):
        x(x),
        y(y),
        width(width),
        height(height)
    {
        display = XOpenDisplay(nullptr);
        root = DefaultRootWindow(display);
    }

    void operator() (cv::Mat& cvImg)
    {
        if(img != nullptr)
            XDestroyImage(img);
        img = XGetImage(display, root, x, y, width, height, AllPlanes, ZPixmap);
        cvImg = cv::Mat(height, width, CV_8UC4, img->data);
    }

    ~ScreenReader()
    {
        if(img != nullptr)
            XDestroyImage(img);
        XCloseDisplay(display);
    }


private:

    Display* display;
    Window root;
    int x,y,width,height;
    XImage* img{nullptr};
};


////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
int main()
{
    //~ ScreenReader screen(0,0,1920,1080);
    ScreenReader screen(400,0,500,800);
    cv::Mat img;
   
    screen(img); 
    cv::imshow("img", img);
        
    while(true) 
    {
        char k = cv::waitKey(10);
        if (k == 'q') break;
    }
}
